from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.orm import sessionmaker, scoped_session, mapper
from sqlalchemy.interfaces import ConnectionProxy

import logging
import sys
import time
import settings as alchemy_settings

class DatabaseConfig(object):
    """
    Generic database configuration container.
    TODO: Needs refactor as codes are now gerbish.
    """
    def __init__(self, db_module_name, db_config):
        self.db_module_name = db_module_name
        self.db_module = db_config.get('db_module', None)
        self.dbengine = db_config.get('dbengine', 'postgres')
        self.dbname = db_config['dbname']
        self.host = db_config.get('host', 'localhost')
        if db_config.get('port'):
            self.port = db_config.get('port')
        elif self.dbengine == 'postgres':
            self.port = db_config.get('port', '5432')
        elif self.dbengine == 'mysql':
            self.port = db_config.get('port', '3306')
        self.user = db_config['user']
        self.password = db_config.get('password')
        if not self.host:
            self.host = '127.0.0.1'

        self.classes = []
        classes = db_config.get('classes', [])
        for class_alias in classes:
            self.classes.append(class_alias)

    def __repr__(self):
        return "DatabaseConfig: module = %(module)s" % {
            'module' : self.db_module_name
        }

    def get_sa_uri(self):
        return ("%(dbengine)s://%(user)s:%(password)s@%(host)s:%(port)s/%(dbname)s") % {
            'dbengine' : self.dbengine,
            'user' : self.user,
            'password' : self.password,
            'host' : self.host,
            'port' : self.port,
            'dbname' : self.dbname
        }

    def get_engine(self, echo=False):
        return create_engine(self.get_sa_uri(), echo=echo,
            proxy=alchemy_settings.ALCHEMY_LOG_SQL and LogQueriesProxy() or ConnectionProxy())

    def get_scoped_session(self):
        return scoped_session(sessionmaker())

    def get_module_path(self):
        pass


class LogQueriesProxy(ConnectionProxy):
    """
    Will use logging module to log queries.
    Usage: just pass instance of this class to engine's configuration.
    ie. engine = create_engine('sqlite://', proxy=LogQueriesProxy())
    
    Establish logging module configuration elsewhere.
    For instance, try to use Djalog or django-logging application.
    """
    def cursor_execute(self, execute, cursor, statement, parameters, context, executemany):
        if not hasattr(logging, 'sql'):
            return execute(cursor, statement, parameters, context)
        now = time.time()
        try:
            return execute(cursor, statement, parameters, context)
        finally:
            total = time.time() - now
            logging.sql("Query: %s" % statement)
            logging.sql("Total Time: %f" % total)
 
